package com.to8to.autotask.deduction;

import static com.to8to.autotask.util.AutoTaskType.POLLINGFEE_DEDUCT;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.elasticsearch.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.to8to.autotask.resulthandler.FailHandler;
import com.to8to.autotask.rpc.CallClient;
import com.to8to.autotask.util.DBUtil;
import com.to8to.autotask.util.Utils;
import com.to8to.es.util.LogUtil;
import com.to8to.thrift.crm.itemdb.TItemFP;
import com.to8to.thrift.crm.query.CompanyInfo;

/**
 * PollingFeeDeductTask.java
 * 作 者：atom.liu
 * 版 本：v2.0
 * 日 期：2014年11月26日
 * 描 述：自动扣轮单费任务。
 *    48小时未查看联系方式(未反馈)、分配时间大于两个半月  且无返款申请状态的 扣除 轮单费。 
 */
public class PollingFeeDeductTask implements Runnable
{
    /**
     * SQL: 获取需要自动扣费的项目
     * iscost not in(1,2) 扣费状态不处于 已扣、已返; [0 待扣 3待定]
     * puttime > 1395763200 分配时间在2014-03-26之后
     * chuli = 0 没有申请返款
     * (fk_time = 0 and upfktime = 0 and puttime < ?) or (puttime < ?) 48小时未反馈 或 分配时间大于两个半月
     */
    private static final String DEDUCT_PROJECT =
        "select * from to8to_yuyue_apply_fp where iscost not in (1,2) and puttime > 1395763200 and chuli = 0 and ( (fk_time = 0 and upfktime = 0 and puttime < ?) or (puttime < ?) )";

    private static final Logger logger = LoggerFactory.getLogger(PollingFeeDeductTask.class);

    @Override
    public void run()
    {
        logger.info("自动扣轮单费任务开始执行...");

        Connection connect = null;

        try
        {
            connect = DBUtil.getConnection();

            //本次查询出需要进行自动扣费的项目
            List<TItemFP> projects = getSatisfyCondition(connect);

            if (Utils.isNullOrEmpty(projects))
            {
                logger.info("本次没有需要扣费的项目!");
                return;
            }

            //将分配记录根据yid进行分组。key:yid, value:List<CompanyInfo>
            Map<Integer, List<CompanyInfo>> map = groupItemFP(projects);

            if (DBUtil.execTaskCountsAtToday(connect, POLLINGFEE_DEDUCT) != 0)
                return;

            recordLog(map, connect);
            CallClient.takeOutMoneyFromCompany(map);
            logger.info("自动扣轮单费任务执行结束...");
        }
        catch (Throwable e)
        {
            logger.error("自动扣轮单费出现异常！{} \n {}", e, LogUtil.logStackTrace(e));
            if (e instanceof SQLException)
                FailHandler.handler(PollingFeeDeductTask.class);
        }
        finally
        {
            DBUtil.releaseSource(null, null, connect);
        }
    }

    /**
     * 记录自动任务信息入库 
     */
    private void recordLog(Map<Integer, List<CompanyInfo>> map, Connection connect)
    {
        List<String> sqls = Lists.newArrayList();
        sqls.add("本次要调用自动扣轮单费的信息：");
        for (Map.Entry<Integer, List<CompanyInfo>> entry : map.entrySet())
        {
            StringBuilder sb = new StringBuilder();
            sb.append("yid: ").append(entry.getKey()).append("[");
            for (CompanyInfo info : entry.getValue())
                sb.append("uid:").append(info.getCompanyid()).append(",fid:").append(info.getFid()).append(" | ");
            sb.append("]");
            sqls.add(sb.toString());
        }
        DBUtil.recordAutoTaskLog(connect, POLLINGFEE_DEDUCT, sqls, true);
    }

    /**
     * 获取符合条件的项目集合 
     */
    private List<TItemFP> getSatisfyCondition(Connection connect) throws SQLException
    {
        int days_2 = Utils.getHourTimePoint(-2 * 24);
        int days_75 = Utils.getDayTimePoint(-75);

        List<TItemFP> projects = new ArrayList<TItemFP>();
        PreparedStatement stat = connect.prepareStatement(DEDUCT_PROJECT);
        stat.setInt(1, days_2);
        stat.setInt(2, days_75);
        ResultSet result = stat.executeQuery();

        while (result.next())
        {
            TItemFP fp = new TItemFP();
            fp.setYid(result.getInt("yid"));
            fp.setXiaohao(result.getInt("xiaohao"));
            fp.setFid(result.getInt("fid"));
            fp.setUid(result.getInt("uid"));
            projects.add(fp);
        }

        DBUtil.releaseSource(result, stat, null);

        return projects;
    }

    /**
     * 根据项目分配记录根据yid进行分组
     */
    private Map<Integer, List<CompanyInfo>> groupItemFP(List<TItemFP> projects)
    {
        Map<Integer, List<CompanyInfo>> map = Maps.newHashMap();
        for (TItemFP fp : projects)
        {
            int yid = fp.getYid();
            CompanyInfo info = new CompanyInfo();
            info.setCompanyid(fp.getUid());
            info.setFid(fp.getFid());
            List<CompanyInfo> list = map.get(yid);
            if (null == list)
            {
                list = new ArrayList<CompanyInfo>();
                map.put(yid, list);
            }
            list.add(info);
        }

        logger.info(String.format("本次需要扣轮单费的项目：%s \r\n共 %s 个!", map.keySet(), map.size()));
        return map;
    }
}
